#ifndef _H_IBAS_IN_
#define _H_IBAS_IN_

#include "ibp_util.h"
#include "ibma_api.h"

#include "IDL_ibas_conf.dsc.h"

#include "ibas_api.h"

extern char     *g_ibp_ibas_kernel_version ;

extern struct IbasEnv		*g_p_ibas_env ;
extern struct FuncStack		*g_funcstack ;

extern sig_atomic_t		g_EXIT_flag ;
extern sig_atomic_t		g_USR2_flag ;

#define IBAS_LISTEN_SOCKFD	"IBAS_LISTEN_SOCKFD"

#define URI_SHOW_STATUS		"/show_status"
#define URI_SHOW_BBSTAT		"/show_bbstat"
#define URI_SHOW_BBDETAIL	"/show_bbdetail"

struct ListenSession
{
	struct NetAddress	netaddr ;
} ;

struct ReportSession
{
	int			hope_to_report ;
	
	struct NetAddress	netaddr ;
	
	struct HttpEnv		*http ;
} ;

struct AcceptedSession
{
	struct NetAddress	netaddr ;
	
	struct HttpEnv		*http ;
	struct HttpSecureEnv	*http_secure_env ;
	struct HttpBuffer	*req_body ;
	struct HttpBuffer	*rsp_body ;
	int			response_flag ;
} ;

struct SoFile
{
	char			so_pathfilename[ IBP_MAXLEN_FILENAME + 1 ] ;
	void			*so_handle ;
	funcIbasSomain		*pfuncIbasSomain ;
	
	char			bin[ IBP_MAXLEN_APP_BIN + 1 ] ;
	struct rb_node		bin_this_rbnode ;
	
	int			call_count ;
	struct rb_node		call_count_this_rbnode ;
	
	int			file_wd ;
	struct rb_node		file_wd_this_rbnode ;
} ;

#define IBAS_MPMMODE_FORK		'F'
#define IBAS_MPMMODE_STATIC_WORKERPOOL	'S'
#define IBAS_MPMMODE_DYNAMIC_WORKERPOOL	'D'

#define IBAS_WORKERSTATUS_NULL		0
#define IBAS_WORKERSTATUS_INITING	'0'
#define IBAS_WORKERSTATUS_IDLE		'I'
#define IBAS_WORKERSTATUS_LISTENING	'L'
#define IBAS_WORKERSTATUS_WORKING	'W'
#define IBAS_WORKERSTATUS_KEEPALIVE	'A'
#define IBAS_WORKERSTATUS_RESTARTING	'R'
#define IBAS_WORKERSTATUS_EXITING	'E'

#define IBAS_WORKERCMD_EXITING		'E'
#define IBAS_WORKERCMD_RELOAD_LOG	'L'

struct IbasWorkerStat
{
	int			initing_count ;
	int			idle_count ;
	int			listening_count ;
	int			working_count ;
	int			keepalive_count ;
	int			restarting_count ;
	int			exiting_count ;
	
	int			load ;
} ;

struct IbasWorkerDetail
{
	int			index ;
	
	pid_t			pid ;
	unsigned char		status ;
	unsigned char		cmd ;
	unsigned int		process_count ;
	
	struct IbasProcessingInfo
	{
		char			node[ IBP_MAXLEN_NODE + 1 ] ;
		char			ip[ IBP_MAXLEN_NODE_IP + 1 ] ;
		char			app[ IBP_MAXLEN_APP + 1 ] ;
		
		struct IbasAddonFiles
		{
			int		req_filecount ;
			char		req_filename[ IBP_MAXCNT_REQUEST_FILES ][ IBP_MAXLEN_FILENAME + 1 ] ;
			char		req_reserve[ IBP_MAXCNT_REQUEST_FILES ] ;
			int		rsp_filecount ;
			char		rsp_filename[ IBP_MAXCNT_RESPONSE_FILES ][ IBP_MAXLEN_FILENAME + 1 ] ;
			char		rsp_reserve[ IBP_MAXCNT_RESPONSE_FILES ] ;
		} addon_files ;
		
		struct IbasTimevalStat
		{
			char		timestamp_str[ 20 + 1 ] ;
			struct timeval	waiting_for_accepting ;
			struct timeval	waiting_for_accepting_elapse ;
			struct timeval	receiving_request ;
			struct timeval	receiving_request_elapse ;
			struct timeval	processing_app ;
			struct timeval	processing_app_elapse ;
			struct timeval	sending_response ;
			struct timeval	sending_response_elapse ;
			struct timeval	finish ;
			struct timeval	total_elapse ;
		} timeval_stat ;
		
		int			timeout ;
		char			output_event_flag ;
	} processing_info ;
	
	int			next_timeout ;
} ;

struct IbasWorkersSapce
{
	struct ShareMemory	shm ;
	struct IbasWorkerStat	*workers_stat ;
	struct IbasWorkerDetail	*worker_detail_array ;
} ;

struct IbasAcceptMutex
{
	struct Semaphore	sem ;
} ;

struct CommandParameter
{
	char			*_action ;
	char			*_show ;
} ;

struct IbasEnv
{
	char			**argv ;
	
	struct CommandParameter	cmd_param ;
	char			*ibas_conf_filename ;
	char			ibas_conf_pathfilename[ IBP_MAXLEN_FILENAME + 1 ] ;
	
	ibas_conf		ibas_conf ;
	struct IbmaConfigSpace	*ibma_config_space ;
	int			mpm_mode ;
	char			node[ IBP_MAXLEN_NODE + 1 ] ;
	
	struct ListenSession	listen_session ;
#if 0
	struct ReportSession	report_session ;
#endif
	struct AcceptedSession	accepted_session ;
	
	struct IbasWorkersSapce	workers_space ;
	struct IbasWorkerDetail	*p_worker_detail ;
	struct IbasAcceptMutex	accept_mutex ;
	
	int			worker_count ;
	int			hope_to_create ;
	int			hope_to_destroy ;
	
	int			inotify_fd ;
	unsigned long		so_cache_count ;
	struct rb_root		so_bin_rbtree ;
	struct rb_root		so_call_count_rbtree ;
	struct rb_root		so_file_wd_rbtree ;
	
	struct NodeSpaceUnit	*p_this_node_unit ;
	struct NodeSpaceUnit	*p_client_node_unit ;
	struct HostSpaceUnit	*p_client_host_unit ;
	struct AppSpaceUnit	*p_this_app_unit ;
	struct SoFile		*p_this_so_file ;
} ;

int LoadConfig( char *config_pathfilename , struct IbasEnv *p_env );

int InitEnvironment( struct IbasEnv *p_env );
void CleanEnvironment( struct IbasEnv *p_env , int rm_ipc_flag );

int _monitor( void *pv );

int AlonerWorker( struct IbasEnv *p_env );
int ManagerWorker( struct IbasEnv *p_env );

int OnReceiveRequest( struct IbasEnv *p_env );
int OnSendResponse( struct IbasEnv *p_env );

#if 0
int OnProcessAliveReport( struct IbasEnv *p_env );
#endif
int OnProcessSoCacheChanged( struct IbasEnv *p_env );
int OnProcessReserveUri( struct IbasEnv *p_env );
int OnDispatchUri( struct IbasEnv *p_env );

int BeforeCallSomain( struct IbasEnv *p_env );
int AfterCallSomain( struct IbasEnv *p_env );

int LinkSoBinTreeNode( struct IbasEnv *p_env , struct SoFile *p_so_file );
struct SoFile *QuerySoBinTreeNode( struct IbasEnv *p_env , struct SoFile *p_so_file );
void UnlinkSoBinTreeNode( struct IbasEnv *p_env , struct SoFile *p_so_file );

int LinkSoCallCountTreeNode( struct IbasEnv *p_env , struct SoFile *p_so_file );
int UpdateSoCallCountTreeNode( struct IbasEnv *p_env , struct SoFile *p_so_file );
void UnlinkMinSoCallCountTreeNode( struct IbasEnv *p_env );
void UnlinkSoCallCountTreeNode( struct IbasEnv *p_env , struct SoFile *p_so_file );

int LinkSoFileWdTreeNode( struct IbasEnv *p_env , struct SoFile *p_so_file );
struct SoFile *QuerySoFileWdTreeNode( struct IbasEnv *p_env , struct SoFile *p_so_file );
void UnlinkSoFileWdTreeNode( struct IbasEnv *p_env , struct SoFile *p_so_file );

void DestroySoFileTree( struct IbasEnv *p_env );

int ShowStatus( struct IbasEnv *p_env );
int ShowBbStat( struct IbasEnv *p_env );
int ShowBbDetail( struct IbasEnv *p_env );

char *GetWorkerStatus( unsigned char status );

void worker_signal_handler( int signo , siginfo_t *info , void *ptr ) ;

#endif

